﻿using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

using Nemerle.Peg;

namespace InfoboxParser
{
  [PegGrammar(
     body,
     grammar {
       any                       = ['\u0000'..'\uFFFF'];
       
       title     : string        = (!"}}" !"\n" any)* "\n"+;
       
       link      : string        = " "* "[[" (!"}}" !"]]" !"\n" any)+ "]]" " "* &"\n";
       namedLink : string        = " "* "[[" (!"}}" !"]]" !"\n" !"|" any)+ "|" (!"}}" !"]]" !"\n" any)+ "]]" " "* &"\n";
       value     : string        = " "* (!"}}" !"\n" any)* " "* &"\n";
       
       attribute : string*string = " "* "|" (!"}}" !"\n" !"=" any)* "=" (namedLink / link / value) "\n"+;
       infobox   : Infobox       = "{{" title attribute* "}}";
       
       infoboxs  : List[Infobox] = infobox+;
       skipCurly : List[Infobox] = "{{";
       body      : List[Infobox] = (!"{{" any)* ((infoboxs / skipCurly) (!"{{" any)*)+
     }
  )]
  public class Parser
  {
    public ParseInfoboxes(data : string) : List[Infobox]
    { 
      def (pos,boxes) = this.TryParse(data);
      if (pos==data.Length) 
        boxes
      else
        List()
    }
    
    
    title(name : NToken, _ : NToken) : string { GetText(name) }
    
    link(_ : NToken, _ : NToken, data : NToken, _ : NToken, _ : NToken) : string { GetText(data) }
    
    namedLink(_ : NToken, _ : NToken, _ : NToken, _ : NToken, name : NToken, _ : NToken,_ : NToken) : string { GetText(name) }
    
    value(_ : NToken, data : NToken, _ : NToken) : string { GetText(data) }
    
    attribute(_ : NToken, _ : NToken, key : NToken, _ : NToken, value : string, _ : NToken) : string*string 
    {
      (GetText(key).Trim(), value.Trim())
    }
    
    infobox(_: NToken, name : string, body : List[string*string], _ : NToken) : Infobox 
    { 
       def info = Infobox();
       info.Name = name;
       foreach((key,value) in body) info.Attributes[key] = value;
       info
    }
    
    
    skipCurly(_ : NToken) : List[Infobox] { List() }
    
    body(_ : NToken, boxes : List[List[Infobox]*NToken]) : List[Infobox]
    {
      boxes.SelectMany((x,_)=>x).ToList()
    }
  }
}
